package com.fang.gateway.security.service;

import com.fang.common.common.CommonConstants;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description 自定义权限 验证 逻辑
 * @Author Bernie
 * @Date 2025/3/9 21:40
 **/
@Component
public class FluxSecurityPermissionEvaluator implements ReactiveAuthorizationManager<AuthorizationContext> {

    @Resource
    private AuthorityService authorityService;

    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext context) {
//        HttpMethod method = request.getMethod(); // 预留
        return authentication
                .map(auth -> {
                    // 获取请求路径
                    String path = context.getExchange().getRequest().getPath().value();
                    if (path.contains(CommonConstants.CommonRequest.PATH_DELETE)) {
                        int lastSlash = path.lastIndexOf(CommonConstants.CommonRequest.PATH_SLASH);
                        path = path.substring(0, lastSlash);
                    }
                    List<String> urlAuthorities = authorityService.findUrlAuthorityByUrl(path);
                    if (urlAuthorities.isEmpty()) {
                        // 没有查到信息，拒绝访问
                        return new AuthorizationDecision(Boolean.FALSE);
                    }
                    // 获取用户权限列表
                    List<String> authorities = auth.getAuthorities().stream()
                            .map(GrantedAuthority::getAuthority)
                            .collect(Collectors.toList());

                    boolean hasPermission = urlAuthorities.stream()
                            .allMatch(authorities::contains); // 全部匹配
                            //.anyMatch(authorities::contains); // 任意匹配
                    return new AuthorizationDecision(hasPermission);
                })
                .defaultIfEmpty(new AuthorizationDecision(Boolean.FALSE));
    }

    @Override
    public Mono<Void> verify(Mono<Authentication> authentication, AuthorizationContext object) {
        return ReactiveAuthorizationManager.super.verify(authentication, object);
    }

}